package org.javaforever.cookieshop.shiro;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;

@Configuration
public class ShiroConfig
{
    /**
    * 这个方法关联一个安全管理器
    * @param defaultWebSecurityManager
    * @return
    */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager defaultWebSecurityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //关联安全管理器
        shiroFilterFactoryBean.getFilters().put("authc", new SimpleFormAuthenticationFilter());
        shiroFilterFactoryBean.getFilters().put("perms", new ShiroPermsAuthorizationFilter());
        shiroFilterFactoryBean.getFilters().put("roles", new ShiroRolesAuthorizationFilter());

        /**
        * 设置拦截URL
        */
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/index.html", "anon");
        map.put("/images/**", "anon");
        map.put("/js/**", "anon");
        map.put("/easyui/**", "anon");
        map.put("/echarts/**", "anon");
        map.put("/uploadjs/**", "anon");
        map.put("/login/index.html", "anon");
        map.put("/login/register.html", "anon");
        map.put("/login/error.html", "anon");
        map.put("/loginController/**", "anon");
        map.put("/*Controller/find*", "authc");
        map.put("/*Controller/listActive*", "authc");
        map.put("/**/*.html", "authc");
        map.put("/roleController/**", "roles[admin]");
        map.put("/permissionController/**", "roles[admin]");
        map.put("/userController/**", "roles[admin]");
        map.put("/goodsController/**", "perms[Goods]");
        map.put("/custOrderController/**", "perms[CustOrder]");
        map.put("/orderItemController/**", "perms[OrderItem]");
        map.put("/recommendController/**", "perms[Recommend]");
        map.put("/typeController/**", "perms[Type]");
        map.put("/admin/**", "roles[admin]");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);

        shiroFilterFactoryBean.setLoginUrl("/login/index.html");
        shiroFilterFactoryBean.setUnauthorizedUrl("/login/noauth.html");

        return  shiroFilterFactoryBean;
    }
    
    /**
    * 解决： 无权限页面不跳转 shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized") 无效
    * shiro的源代码ShiroFilterFactoryBean.Java定义的filter必须满足filter instanceof AuthorizationFilter，
    * 只有perms，roles，ssl，rest，port才是属于AuthorizationFilter，而anon，authcBasic，auchc，user是AuthenticationFilter，
    * 所以unauthorizedUrl设置后页面不跳转 Shiro注解模式下，登录失败与没有权限都是通过抛出异常。
    * 并且默认并没有去处理或者捕获这些异常。在SpringMVC下需要配置捕获相应异常来通知用户信息
    * @return
    */
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver simpleMappingExceptionResolver=new SimpleMappingExceptionResolver();
        Properties properties=new Properties();
        //这里的 /unauthorized 是页面，不是访问的路径
        properties.setProperty("org.apache.shiro.authz.UnauthorizedException","/unauthorized");
        properties.setProperty("org.apache.shiro.authz.UnauthenticatedException","/unauthorized");
        simpleMappingExceptionResolver.setExceptionMappings(properties);
        return simpleMappingExceptionResolver;
    }
    
    /**
    * 获得一个安全管理器
    * 这个方法关联一个realm类
    * @param userRealm
    * @return
    */
    @Bean(name = "manager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("realm") UserRealm userRealm)
    {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(userRealm); //设置realm
        manager.setSessionManager(getSessionManager());

        return manager;
    }

    /**
    * 获得一个realm类
    * @return
    */
    @Bean(name = "realm")
    public UserRealm getRealm()
    {
        return new UserRealm();
    }

    @Bean(name = "shiroDialect")
    public ShiroDialect getShiroDialect()
    {
        return new ShiroDialect();
    }
    //添加bean
    /**
    * 自定义sessionManager
    * @return
    */
    @Bean
    public SessionManager getSessionManager(){
        MySessionManager shiroSessionManager = new MySessionManager();
        //这里可以不设置。Shiro有默认的session管理。如果缓存为Redis则需改用Redis的管理
        //shiroSessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
        return shiroSessionManager;
    }
}
